// service/comment_service.js
const { UniqueConstraintError, Op, or} = require('sequelize');
const { sequelize } = require('../config/mysql_config');
const ApiError = require('../tool/utils/api_error');

const User = require('../model/User');
const Advisor = require('../model/Advisor');
const {Order} = require('../model/Order');
const OrderComment = require('../model/Comment');
const { addLedger } = require('./coin_ledger');
const {ORDER_STATUS} = require("../model/other/enums");

/**
 * 下单后对订单进行评论（可选打赏）
 * 返回：订单详情 + 新增评论 + 顾问的最新评分/评论数（以及打赏后的余额快照）
 */
async function createOrderCommentWithTipService({ userId, orderId, advisorId, rating, content, isToTip, tipCoin }) {
    return await sequelize.transaction(async (t) => {
        // 0) 基本检查
        if (isToTip === 1 && (!Number.isInteger(tipCoin) || tipCoin <= 0)) {
            throw ApiError.BadRequest('tipCoin 必须为正整数且大于 0');
        }

        // 1) 锁订单，确保订单归属 & 防止并发写
        const order = await Order.findOne({
            where: { id: orderId, userId, advisorId },
            transaction: t,
            lock: t.LOCK.UPDATE,
        });
        if (!order) throw ApiError.BadRequest('订单不存在或不属于该用户/顾问');
        if (order.status === ORDER_STATUS.CANCELLED) throw ApiError.BadRequest('订单已取消，不能评论')

        // 限制：每个订单只能评价一次
        const existed = await OrderComment.findOne({ where: { orderId }, transaction: t, lock: t.LOCK.UPDATE });
        if (existed) throw ApiError.BadRequest('该订单已完成评价');

        // 2) 创建评论
        const commentAt = new Date();
        let newComment;
        try {
            newComment = await OrderComment.create(
                {
                    orderId,
                    userId,
                    advisorId,
                    rating,
                    content,
                    isToTip,
                    tipCoin: isToTip ? tipCoin : 0,
                    commentAt,
                },
                { transaction: t }
            );
        } catch (err) {
            if (err instanceof UniqueConstraintError) {
                throw ApiError.BadRequest('该订单已完成评价');
            }
            throw err;
        }

        // 3) 更新顾问评分/评论数（加锁保证并发安全）
        const adv = await Advisor.findByPk(advisorId, { transaction: t, lock: t.LOCK.UPDATE });
        if (!adv) throw ApiError.BadRequest('顾问不存在');

        const oldCnt = Number(adv.commentCnt || 0);
        const oldScore = Number(adv.score || 0);
        const newCnt = oldCnt + 1;
        const newScore = Number(((oldScore * oldCnt + Number(rating)) / newCnt).toFixed(2));

        await adv.update({ commentCnt: newCnt, score: newScore }, { transaction: t });

        // 4) 如需打赏：扣用户、加顾问 + 写两条流水
        let tipResult = null;
        if (isToTip === 1) {
            const u = await User.findByPk(userId, { transaction: t, lock: t.LOCK.UPDATE });
            if (!u) throw ApiError.BadRequest('用户不存在');

            const userCoin = Number(u.coin || 0);
            if (userCoin < tipCoin) throw ApiError.BadRequest('余额不足，无法打赏');

            const advCoinBefore = Number(adv.coin || 0);
            const userNewCoin = userCoin - tipCoin;
            const advisorNewCoin = advCoinBefore + tipCoin;

            await u.update({ coin: userNewCoin }, { transaction: t });
            await adv.update({ coin: advisorNewCoin }, { transaction: t });

            // 支出流水（用户）
            await addLedger(t, {
                accountType: 'user',
                accountId: userId,
                orderId,
                bizType: 'TIP_PAY',
                amount: -tipCoin,
                balanceAfter: userNewCoin,
            });

            // 收入流水（顾问）
            await addLedger(t, {
                accountType: 'advisor',
                accountId: advisorId,
                orderId,
                bizType: 'TIP_INCOME',
                amount: tipCoin,
                balanceAfter: advisorNewCoin,
            });

            tipResult = {
                tipCoin,
                userNewCoin,
                advisorNewCoin,
            };
        }

        // 5) 返回“刚刚创建的订单详情”
        // 返回订单基础信息 + 新增评论 + 顾问评星汇总 + 打赏结果
        const orderPlain = order.get({ plain: true });
        const commentPlain = newComment.get({ plain: true });

        return {
            order: orderPlain,
            comment: {
                id: commentPlain.id,
                orderId: commentPlain.orderId,
                userId: commentPlain.userId,
                advisorId: commentPlain.advisorId,
                rating: Number(commentPlain.rating),
                content: commentPlain.content || '',
                commentAt: commentPlain.commentAt,
                advisorReply: commentPlain.replyContent ?? null,
                replyAt: commentPlain.replyAt ?? null,
                isToTip,
                tipCoin: isToTip ? tipCoin : 0,
            },
        };
    });
}


async function replyCommentByAdvisorService({ advisorId, commentId, replyContent }) {
    return await sequelize.transaction(async (t) => {
        // 1) 锁住评论行，避免并发覆盖
        const comment = await OrderComment.findByPk(commentId, {
            transaction: t,
            lock: t.LOCK.UPDATE,
        });
        if (!comment) throw ApiError.NotFound('评论不存在');
        // 2) 权限校验：仅允许该评论对应的顾问回复
        if (Number(comment.advisorId) !== Number(advisorId)) {
            throw ApiError.Unauthorized('无权限回复该评论');
        }
        if(comment.replyContent) throw ApiError.BadRequest("该评论已回复")

        // 3) 写入回复内容与时间
        const replyAt = new Date();
        await comment.update(
            { replyContent, replyAt },
            { transaction: t }
        );

        // 4) 返回
        const c = comment.get({ plain: true });
        return {
            commentId: c.id,
            advisorId: c.advisorId,
            userId: c.userId,
            rating: Number(c.rating),
            content: c.content || '',
            commentAt: c.commentAt,
            advisorReply: c.replyContent ?? null,
            replyAt: c.replyAt ?? null,
        };
    });
}

module.exports = {
    createOrderCommentWithTipService,
    replyCommentByAdvisorService
};